package de.lulusoft.anothertorrent.core.rtorrent;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;

import org.apache.xmlrpc.XmlRpcException;

import de.lulusoft.anothertorrent.core.exceptions.AnotherTorrentException;
import de.lulusoft.anothertorrent.core.exceptions.ExceptionHandler;
import de.lulusoft.anothertorrent.core.exceptions.RTorrentNoInfoHashException;
import de.lulusoft.anothertorrent.core.servers.Server;
import de.lulusoft.anothertorrent.core.xmlrpc.ConnectionManager;
import de.lulusoft.anothertorrent.core.xmlrpc.XmlrpcManager;
import de.lulusoft.anothertorrent.core.xmlrpc.XmlrpcSocketManager;

public class RTorrentManager {
	

	private ConnectionManager connectionManager = null;
	private Server server;
	
	public RTorrentManager(Server server) throws AnotherTorrentException
	{
		try {
			this.server = server;
			switch (server.getType())
			{
			case XMLRPC:
				connectionManager = new XmlrpcManager(server.getUrl(), server.isI8Support());
				break;
			case SOCKET:
				connectionManager = new XmlrpcSocketManager(server.getHost(), server.getPort(), server.isI8Support());
				break;
			}

			connectionManager.connect();
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	// TODO : remove
	public ConnectionManager getXmlrpcManager()
	{
		return connectionManager;
	}

	/**
	 * Get List of available Views.
	 * @return List of available Views.
	 * @throws AnotherTorrentException 
	 */
	public ArrayList<String> getViewNames() throws AnotherTorrentException
	{
		ArrayList<String> retval = new ArrayList<String>();
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("view_list");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof Object[])
			for (Object r : ((Object[])result))
				retval.add(r.toString());
		return retval;
	}
	
	/**
	 * Returns a View with all torrents.
	 * @param viewName
	 * @return
	 * @throws AnotherTorrentException 
	 */
	public View getView(String viewName) throws AnotherTorrentException
	{
		View view = new View(viewName);
		
		Object result;
		try {
			result = connectionManager.sendCommand("d.multicall", 
					new Object[]{viewName,"d.get_base_filename=","d.get_base_path=",
					"d.get_bytes_done=","d.get_chunk_size=","d.get_chunks_hashed=",
					"d.get_complete=","d.get_completed_bytes=","d.get_completed_chunks=",
					"d.get_connection_current=","d.get_connection_leech=","d.get_connection_seed=",
					"d.get_creation_date=","d.get_directory=","d.get_down_rate=","d.get_down_total=",
					"d.get_free_diskspace=","d.get_hash=","d.get_hashing=","d.get_ignore_commands=",
					"d.get_left_bytes=","d.get_local_id=","d.get_local_id_html=",
					"d.get_max_file_size=","d.get_message=","d.get_peers_min=","d.get_name=",
					"d.get_peer_exchange=","d.get_peers_accounted=","d.get_peers_complete=",
					"d.get_peers_connected=","d.get_peers_max=","d.get_peers_not_connected=",
					"d.get_priority=","d.get_priority_str=","d.get_ratio=","d.get_size_bytes=",
					"d.get_size_chunks=","d.get_size_files=","d.get_skip_rate=","d.get_skip_total=",
					"d.get_state=","d.get_state_changed=","d.get_tied_to_file=","d.get_tracker_focus=",
					"d.get_tracker_numwant=","d.get_tracker_size=","d.get_up_rate=","d.get_up_total=",
					"d.get_uploads_max=","d.is_active=","d.is_hash_checked=","d.is_hash_checking=",
					"d.is_multi_file=","d.is_open=","d.is_private=", "d.get_custom1=", "d.get_custom2=",
					"d.get_custom3=", "d.get_custom4=", "d.get_custom5="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}

		if (result instanceof Object[])
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] t = (Object[])r;
					Torrent torrent = new Torrent(t[0].toString(),t[1].toString(),(Long)t[2],
							(Long)t[3],(Long)t[4],(Long)t[5],
							(Long)t[6],(Long)t[7],
							(String)t[8],(String)t[9],
							(String)t[10],(Long)t[11],t[12].toString(),
							(Long)t[13],(Long)t[14],(Long)t[15],t[16].toString(),(Long)t[17],
							(Long)t[18],(Long)t[19],(String)t[20],
							(String)t[21],(Long)t[22],(String)t[23],
							(Long)t[24],t[25].toString(),(Long)t[26],
							(Long)t[27],(Long)t[28],
							(Long)t[29],(Long)t[30],(Long)t[31],
							(Long)t[32],t[33].toString(),(Long)t[34],(Long)t[35],
							(Long)t[36],(Long)t[37],(Long)t[38],(Long)t[39],(Long)t[40],
							(Long)t[41],(String)t[42],(Long)t[43],
							(Long)t[44],(Long)t[45],(Long)t[46],
							(Long)t[47],(Long)t[48],(Long)t[49],
							(Long)t[50],(Long)t[51],(Long)t[52],
							(Long)t[53],(Long)t[54],(String)t[55],(String)t[56],(String)t[57],
							(String)t[58],(String)t[59],true, server);
					view.addTorrent(torrent);
				}
			}
		
		return view;
	}
	
	/**
	 * Updates a View.
	 * @param view
	 * @return
	 * @throws AnotherTorrentException 
	 */
	public void updateView(View view) throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendCommand("d.multicall", 
					new Object[]{view.getName(),"d.get_base_filename=","d.get_base_path=",
					"d.get_bytes_done=","d.get_chunk_size=","d.get_chunks_hashed=",
					"d.get_complete=","d.get_completed_bytes=","d.get_completed_chunks=",
					"d.get_connection_current=","d.get_connection_leech=","d.get_connection_seed=",
					"d.get_creation_date=","d.get_directory=","d.get_down_rate=","d.get_down_total=",
					"d.get_free_diskspace=","d.get_hash=","d.get_hashing=","d.get_ignore_commands=",
					"d.get_left_bytes=","d.get_local_id=","d.get_local_id_html=",
					"d.get_max_file_size=","d.get_message=","d.get_peers_min=","d.get_name=",
					"d.get_peer_exchange=","d.get_peers_accounted=","d.get_peers_complete=",
					"d.get_peers_connected=","d.get_peers_max=","d.get_peers_not_connected=",
					"d.get_priority=","d.get_priority_str=","d.get_ratio=","d.get_size_bytes=",
					"d.get_size_chunks=","d.get_size_files=","d.get_skip_rate=","d.get_skip_total=",
					"d.get_state=","d.get_state_changed=","d.get_tied_to_file=","d.get_tracker_focus=",
					"d.get_tracker_numwant=","d.get_tracker_size=","d.get_up_rate=","d.get_up_total=",
					"d.get_uploads_max=","d.is_active=","d.is_hash_checked=","d.is_hash_checking=",
					"d.is_multi_file=","d.is_open=","d.is_private=", "d.get_custom1=", "d.get_custom2=",
					"d.get_custom3=", "d.get_custom4=", "d.get_custom5="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}

		if (result instanceof Object[])
		{
			// Mark all existing torrents
			Iterator<Torrent> it = view.getTorrents().iterator();
			while (it.hasNext())
				it.next().setExisting(false);
			
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] t = (Object[])r;
					Torrent torrent = new Torrent(t[0].toString(),t[1].toString(),(Long)t[2],
							(Long)t[3],(Long)t[4],(Long)t[5],
							(Long)t[6],(Long)t[7],
							(String)t[8],(String)t[9],
							(String)t[10],(Long)t[11],t[12].toString(),
							(Long)t[13],(Long)t[14],(Long)t[15],t[16].toString(),(Long)t[17],
							(Long)t[18],(Long)t[19],(String)t[20],
							(String)t[21],(Long)t[22],(String)t[23],
							(Long)t[24],t[25].toString(),(Long)t[26],
							(Long)t[27],(Long)t[28],
							(Long)t[29],(Long)t[30],(Long)t[31],
							(Long)t[32],t[33].toString(),(Long)t[34],(Long)t[35],
							(Long)t[36],(Long)t[37],(Long)t[38],(Long)t[39],(Long)t[40],
							(Long)t[41],(String)t[42],(Long)t[43],
							(Long)t[44],(Long)t[45],(Long)t[46],
							(Long)t[47],(Long)t[48],(Long)t[49],
							(Long)t[50],(Long)t[51],(Long)t[52],
							(Long)t[53],(Long)t[54],(String)t[55],(String)t[56],(String)t[57],
							(String)t[58],(String)t[59],true, server);
					
					// Update existing torrent
					Torrent tExist = view.getTorrents().getByHash(torrent.getHash());
					if (tExist != null)
					{
						int updated = tExist.update(t[0].toString(),t[1].toString(),(Long)t[2],
								(Long)t[3],(Long)t[4],(Long)t[5],
								(Long)t[6],(Long)t[7],
								(String)t[8],(String)t[9],
								(String)t[10],(Long)t[11],t[12].toString(),
								(Long)t[13],(Long)t[14],(Long)t[15],t[16].toString(),(Long)t[17],
								(Long)t[18],(Long)t[19],(String)t[20],
								(String)t[21],(Long)t[22],(String)t[23],
								(Long)t[24],t[25].toString(),(Long)t[26],
								(Long)t[27],(Long)t[28],
								(Long)t[29],(Long)t[30],(Long)t[31],
								(Long)t[32],t[33].toString(),(Long)t[34],(Long)t[35],
								(Long)t[36],(Long)t[37],(Long)t[38],(Long)t[39],(Long)t[40],
								(Long)t[41],(String)t[42],(Long)t[43],
								(Long)t[44],(Long)t[45],(Long)t[46],
								(Long)t[47],(Long)t[48],(Long)t[49],
								(Long)t[50],(Long)t[51],(Long)t[52],
								(Long)t[53],(Long)t[54],(String)t[55],(String)t[56],(String)t[57],
								(String)t[58],(String)t[59],true, server);
						if (updated == 1)
							view.updatedTorrents.add(tExist);
						torrent = null;
					}
					else// Or add new one
					{
						view.addTorrent(torrent);
						view.newTorrents.add(torrent);
					}
				}
			}
		}
		
		// Remove not existing torrents
		Iterator<Torrent> it = view.getTorrents().iterator();
		while (it.hasNext())
		{
			Torrent t = it.next();
			if (!t.isExisting())
			{
				view.removedTorrents.add(t);
				it.remove();
			}
		}
	}
	
	/**
	 * Updates a torrent. The hash has to be set already.
	 * @param torrent
	 * @throws AnotherTorrentException 
	 */
	@SuppressWarnings("unchecked")
	public void updateTorrent(Torrent torrent) throws AnotherTorrentException
	{
		Hashtable<String, Object> map_get_base_filename = new Hashtable<String, Object>();
		map_get_base_filename.put("methodName", "d.get_base_filename");
		map_get_base_filename.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_base_path = new Hashtable<String, Object>();
		map_get_base_path.put("methodName", "d.get_base_path");
		map_get_base_path.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_bytes_done = new Hashtable<String, Object>();
		map_get_bytes_done.put("methodName", "d.get_bytes_done");
		map_get_bytes_done.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_chunk_size = new Hashtable<String, Object>();
		map_get_chunk_size.put("methodName", "d.get_chunk_size");
		map_get_chunk_size.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_chunks_hashed = new Hashtable<String, Object>();
		map_get_chunks_hashed.put("methodName", "d.get_chunks_hashed");
		map_get_chunks_hashed.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_complete = new Hashtable<String, Object>();
		map_get_complete.put("methodName", "d.get_complete");
		map_get_complete.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_completed_bytes = new Hashtable<String, Object>();
		map_get_completed_bytes.put("methodName", "d.get_completed_bytes");
		map_get_completed_bytes.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_completed_chunks = new Hashtable<String, Object>();
		map_get_completed_chunks.put("methodName", "d.get_completed_chunks");
		map_get_completed_chunks.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_connection_current = new Hashtable<String, Object>();
		map_get_connection_current.put("methodName", "d.get_connection_current");
		map_get_connection_current.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_connection_leech = new Hashtable<String, Object>();
		map_get_connection_leech.put("methodName", "d.get_connection_leech");
		map_get_connection_leech.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_connection_seed = new Hashtable<String, Object>();
		map_get_connection_seed.put("methodName", "d.get_connection_seed");
		map_get_connection_seed.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_creation_date = new Hashtable<String, Object>();
		map_get_creation_date.put("methodName", "d.get_creation_date");
		map_get_creation_date.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_directory = new Hashtable<String, Object>();
		map_get_directory.put("methodName", "d.get_directory");
		map_get_directory.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_down_rate = new Hashtable<String, Object>();
		map_get_down_rate.put("methodName", "d.get_down_rate");
		map_get_down_rate.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_down_total = new Hashtable<String, Object>();
		map_get_down_total.put("methodName", "d.get_down_total");
		map_get_down_total.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_free_diskspace = new Hashtable<String, Object>();
		map_get_free_diskspace.put("methodName", "d.get_free_diskspace");
		map_get_free_diskspace.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_hash = new Hashtable<String, Object>();
		map_get_hash.put("methodName", "d.get_hash");
		map_get_hash.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_hashing = new Hashtable<String, Object>();
		map_get_hashing.put("methodName", "d.get_hashing");
		map_get_hashing.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_ignore_commands = new Hashtable<String, Object>();
		map_get_ignore_commands.put("methodName", "d.get_ignore_commands");
		map_get_ignore_commands.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_left_bytes = new Hashtable<String, Object>();
		map_get_left_bytes.put("methodName", "d.get_left_bytes");
		map_get_left_bytes.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_local_id = new Hashtable<String, Object>();
		map_get_local_id.put("methodName", "d.get_local_id");
		map_get_local_id.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_local_id_html = new Hashtable<String, Object>();
		map_get_local_id_html.put("methodName", "d.get_local_id_html");
		map_get_local_id_html.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_max_file_size = new Hashtable<String, Object>();
		map_get_max_file_size.put("methodName", "d.get_max_file_size");
		map_get_max_file_size.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_message = new Hashtable<String, Object>();
		map_get_message.put("methodName", "d.get_message");
		map_get_message.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_min = new Hashtable<String, Object>();
		map_get_peers_min.put("methodName", "d.get_peers_min");
		map_get_peers_min.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_name = new Hashtable<String, Object>();
		map_get_name.put("methodName", "d.get_name");
		map_get_name.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peer_exchange = new Hashtable<String, Object>();
		map_get_peer_exchange.put("methodName", "d.get_peer_exchange");
		map_get_peer_exchange.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_accounted = new Hashtable<String, Object>();
		map_get_peers_accounted.put("methodName", "d.get_peers_accounted");
		map_get_peers_accounted.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_complete = new Hashtable<String, Object>();
		map_get_peers_complete.put("methodName", "d.get_peers_complete");
		map_get_peers_complete.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_connected = new Hashtable<String, Object>();
		map_get_peers_connected.put("methodName", "d.get_peers_connected");
		map_get_peers_connected.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_max = new Hashtable<String, Object>();
		map_get_peers_max.put("methodName", "d.get_peers_max");
		map_get_peers_max.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_peers_not_connected = new Hashtable<String, Object>();
		map_get_peers_not_connected.put("methodName", "d.get_peers_not_connected");
		map_get_peers_not_connected.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_priority = new Hashtable<String, Object>();
		map_get_priority.put("methodName", "d.get_priority");
		map_get_priority.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_priority_str = new Hashtable<String, Object>();
		map_get_priority_str.put("methodName", "d.get_priority_str");
		map_get_priority_str.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_ratio = new Hashtable<String, Object>();
		map_get_ratio.put("methodName", "d.get_ratio");
		map_get_ratio.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_size_bytes = new Hashtable<String, Object>();
		map_get_size_bytes.put("methodName", "d.get_size_bytes");
		map_get_size_bytes.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_size_chunks = new Hashtable<String, Object>();
		map_get_size_chunks.put("methodName", "d.get_size_chunks");
		map_get_size_chunks.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_size_files = new Hashtable<String, Object>();
		map_get_size_files.put("methodName", "d.get_size_files");
		map_get_size_files.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_skip_rate = new Hashtable<String, Object>();
		map_get_skip_rate.put("methodName", "d.get_skip_rate");
		map_get_skip_rate.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_skip_total = new Hashtable<String, Object>();
		map_get_skip_total.put("methodName", "d.get_skip_total");
		map_get_skip_total.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_state = new Hashtable<String, Object>();
		map_get_state.put("methodName", "d.get_state");
		map_get_state.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_state_changed = new Hashtable<String, Object>();
		map_get_state_changed.put("methodName", "d.get_state_changed");
		map_get_state_changed.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_tied_to_file = new Hashtable<String, Object>();
		map_get_tied_to_file.put("methodName", "d.get_tied_to_file");
		map_get_tied_to_file.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_tracker_focus = new Hashtable<String, Object>();
		map_get_tracker_focus.put("methodName", "d.get_tracker_focus");
		map_get_tracker_focus.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_tracker_numwant = new Hashtable<String, Object>();
		map_get_tracker_numwant.put("methodName", "d.get_tracker_numwant");
		map_get_tracker_numwant.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_tracker_size = new Hashtable<String, Object>();
		map_get_tracker_size.put("methodName", "d.get_tracker_size");
		map_get_tracker_size.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_up_rate = new Hashtable<String, Object>();
		map_get_up_rate.put("methodName", "d.get_up_rate");
		map_get_up_rate.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_up_total = new Hashtable<String, Object>();
		map_get_up_total.put("methodName", "d.get_up_total");
		map_get_up_total.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_uploads_max = new Hashtable<String, Object>();
		map_get_uploads_max.put("methodName", "d.get_uploads_max");
		map_get_uploads_max.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_active = new Hashtable<String, Object>();
		map_is_active.put("methodName", "d.is_active");
		map_is_active.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_hash_checked = new Hashtable<String, Object>();
		map_is_hash_checked.put("methodName", "d.is_hash_checked");
		map_is_hash_checked.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_hash_checking = new Hashtable<String, Object>();
		map_is_hash_checking.put("methodName", "d.is_hash_checking");
		map_is_hash_checking.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_multi_file = new Hashtable<String, Object>();
		map_is_multi_file.put("methodName", "d.is_multi_file");
		map_is_multi_file.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_open = new Hashtable<String, Object>();
		map_is_open.put("methodName", "d.is_open");
		map_is_open.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_is_private = new Hashtable<String, Object>();
		map_is_private.put("methodName", "d.is_private");
		map_is_private.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_custom1 = new Hashtable<String, Object>();
		map_get_custom1.put("methodName", "d.get_custom1");
		map_get_custom1.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_custom2 = new Hashtable<String, Object>();
		map_get_custom2.put("methodName", "d.get_custom2");
		map_get_custom2.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_custom3 = new Hashtable<String, Object>();
		map_get_custom3.put("methodName", "d.get_custom3");
		map_get_custom3.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_custom4 = new Hashtable<String, Object>();
		map_get_custom4.put("methodName", "d.get_custom4");
		map_get_custom4.put("params", new Object[]{torrent.getHash()});

		Hashtable<String, Object> map_get_custom5 = new Hashtable<String, Object>();
		map_get_custom5.put("methodName", "d.get_custom5");
		map_get_custom5.put("params", new Object[]{torrent.getHash()});

		
		Object result;
		try {
			result = connectionManager.sendCommand("system.multicall",new Object[]{new Object[]{
					map_get_base_filename,
					map_get_base_path,
					map_get_bytes_done,
					map_get_chunk_size,
					map_get_chunks_hashed,
					map_get_complete,
					map_get_completed_bytes,
					map_get_completed_chunks,
					map_get_connection_current,
					map_get_connection_leech,
					map_get_connection_seed,
					map_get_creation_date,
					map_get_directory,
					map_get_down_rate,
					map_get_down_total,
					map_get_free_diskspace,
					map_get_hash,
					map_get_hashing,
					map_get_ignore_commands,
					map_get_left_bytes,
					map_get_local_id,
					map_get_local_id_html,
					map_get_max_file_size,
					map_get_message,
					map_get_peers_min,
					map_get_name,
					map_get_peer_exchange,
					map_get_peers_accounted,
					map_get_peers_complete,
					map_get_peers_connected,
					map_get_peers_max,
					map_get_peers_not_connected,
					map_get_priority,
					map_get_priority_str,
					map_get_ratio,
					map_get_size_bytes,
					map_get_size_chunks,
					map_get_size_files,
					map_get_skip_rate,
					map_get_skip_total,
					map_get_state,
					map_get_state_changed,
					map_get_tied_to_file,
					map_get_tracker_focus,
					map_get_tracker_numwant,
					map_get_tracker_size,
					map_get_up_rate,
					map_get_up_total,
					map_get_uploads_max,
					map_is_active,
					map_is_hash_checked,
					map_is_hash_checking,
					map_is_multi_file,
					map_is_open,
					map_is_private,
					map_get_custom1,
					map_get_custom2,
					map_get_custom3,
					map_get_custom4,
					map_get_custom5
					}});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		if (result instanceof Object[])
		{
					Object[] t = (Object[])result;
					// ckeck if we have a faultCode
					for (int i = 0; i < t.length; i++)
						if (t[i] instanceof HashMap)
						{
							HashMap<String, Object> hm = (HashMap)t[0];
							String faultString = (String) hm.get("faultString");
							if (faultString != null)
							{
								if (faultString.equals(ExceptionHandler.ERROR_INFOHASH))
									throw new RTorrentNoInfoHashException(ExceptionHandler.ERROR_INFOHASH);
							}
							
						}
					torrent.update((((Object[])t[0])[0]).toString(),(((Object[])t[1])[0]).toString(),(Long)(((Object[])t[2])[0]),
							(Long)(((Object[])t[3])[0]),(Long)(((Object[])t[4])[0]),(Long)(((Object[])t[5])[0]),
							(Long)(((Object[])t[6])[0]),(Long)(((Object[])t[7])[0]),
							(String)(((Object[])t[8])[0]),(String)(((Object[])t[9])[0]),
							(String)(((Object[])t[10])[0]),(Long)(((Object[])t[11])[0]),(((Object[])t[12])[0]).toString(),
							(Long)(((Object[])t[13])[0]),(Long)(((Object[])t[14])[0]),(Long)(((Object[])t[15])[0]),(((Object[])t[16])[0]).toString(),(Long)(((Object[])t[17])[0]),
							(Long)(((Object[])t[18])[0]),(Long)(((Object[])t[19])[0]),(String)(((Object[])t[20])[0]),
							(String)(((Object[])t[21])[0]),(Long)(((Object[])t[22])[0]),(String)(((Object[])t[23])[0]),
							(Long)(((Object[])t[24])[0]),(((Object[])t[25])[0]).toString(),(Long)(((Object[])t[26])[0]),
							(Long)(((Object[])t[27])[0]),(Long)(((Object[])t[28])[0]),
							(Long)(((Object[])t[29])[0]),(Long)(((Object[])t[30])[0]),(Long)(((Object[])t[31])[0]),
							(Long)(((Object[])t[32])[0]),(((Object[])t[33])[0]).toString(),(Long)(((Object[])t[34])[0]),(Long)(((Object[])t[35])[0]),
							(Long)(((Object[])t[36])[0]),(Long)(((Object[])t[37])[0]),(Long)(((Object[])t[38])[0]),(Long)(((Object[])t[39])[0]),(Long)(((Object[])t[40])[0]),
							(Long)(((Object[])t[41])[0]),(String)(((Object[])t[42])[0]),(Long)(((Object[])t[43])[0]),
							(Long)(((Object[])t[44])[0]),(Long)(((Object[])t[45])[0]),(Long)(((Object[])t[46])[0]),
							(Long)(((Object[])t[47])[0]),(Long)(((Object[])t[48])[0]),(Long)(((Object[])t[49])[0]),
							(Long)(((Object[])t[50])[0]),(Long)(((Object[])t[51])[0]),(Long)(((Object[])t[52])[0]),
							(Long)(((Object[])t[53])[0]),(Long)(((Object[])t[54])[0]),(String)(((Object[])t[55])[0]),(String)(((Object[])t[56])[0]),
							(String)(((Object[])t[57])[0]),(String)(((Object[])t[58])[0]),(String)(((Object[])t[59])[0]),true, server);
			}

	}
	
	/**
	 * Loads all files from the given torrent from the server into the files array of
	 * the torrent.
	 * @param hash
	 * @return
	 * @throws AnotherTorrentException 
	 */
	public void getFiles(Torrent torrent) throws AnotherTorrentException
	{
		// clear old files
		torrent.getFiles().clear();
		
		// get new files
		Object result;
		try {
			result = connectionManager.sendCommand("f.multicall", 
					new Object[]{torrent.getHash(), "","f.get_completed_chunks=","f.get_frozen_path=",
						"f.is_created=","f.is_open=","f.get_last_touched=","f.get_match_depth_next=",
						"f.get_match_depth_prev=","f.get_offset=","f.get_path=",
						"f.get_path_components=","f.get_path_depth=","f.get_priority=",
						"f.get_range_first=","f.get_range_second=","f.get_size_bytes=",
						"f.get_size_chunks="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		// add new files
		if (result instanceof Object[])
		{
			Long index = 0L;
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					File file = new File((Long)f[0], f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],(Long)f[5],(Long)f[6],(Long)f[7],f[8].toString(),
							f[9].toString(),(Long)f[10],(Long)f[11],(Long)f[12],(Long)f[13],
							(Long)f[14],(Long)f[15], index++, torrent);
					file.addPropertyChangeListener(torrent.getFiles());
					torrent.addFile(file);
				}
			}
		}
	}
	
	
	
	/**
	 * Updates the given Files for a torrent.
	 * @param hash
	 * @return
	 * @throws AnotherTorrentException 
	 */
	public void updateFiles(Torrent torrent) throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendCommand("f.multicall", 
					new Object[]{torrent.getHash(), "","f.get_completed_chunks=","f.get_frozen_path=",
						"f.is_created=","f.is_open=","f.get_last_touched=","f.get_match_depth_next=",
						"f.get_match_depth_prev=","f.get_offset=","f.get_path=",
						"f.get_path_components=","f.get_path_depth=","f.get_priority=",
						"f.get_range_first=","f.get_range_second=","f.get_size_bytes=",
						"f.get_size_chunks="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		if (result instanceof Object[])
		{
			Long index = 0L;
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					int updated = torrent.getFiles().get(index.intValue()).update(
							(Long)f[0], f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],(Long)f[5],(Long)f[6],(Long)f[7],f[8].toString(),
							f[9].toString(),(Long)f[10],(Long)f[11],(Long)f[12],(Long)f[13],
							(Long)f[14],(Long)f[15]);
					if (updated == 1) // Add file to updatedFiles
						torrent.getFiles().updatedFiles.add(torrent.getFiles().get(index.intValue()));
					index++;
				}
			}
		}
	}
	
	public void getPeers(Torrent torrent) throws AnotherTorrentException
	{
		torrent.getPeers().clear();
		
		Object result;
		try {
			result = connectionManager.sendCommand("p.multicall", 
					new Object[]{torrent.getHash(), "","p.get_address=","p.get_client_version=",
					"p.get_completed_percent=","p.get_down_rate=","p.get_down_total=",
					"p.get_id=","p.get_id_html=","p.get_options_str=","p.get_peer_rate=",
					"p.get_peer_total=","p.get_port=","p.get_up_rate=","p.get_up_total=",
					"p.is_encrypted=","p.is_incoming=","p.is_obfuscated=","p.is_snubbed="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		
		if (result instanceof Object[])
		{
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					Peer peer = new Peer(f[0].toString(), f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],f[5].toString(),f[6].toString(),f[7].toString(),(Long)f[8],
							(Long)f[9],(Long)f[10],(Long)f[11],(Long)f[12],(Long)f[13],
							(Long)f[14],(Long)f[15],(Long)f[16], torrent, true);
					peer.addPropertyChangeListener(torrent.getPeers());
					torrent.getPeers().add(peer);
				}
			}
		}
	}
	
	public void updatePeers(Torrent torrent) throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendCommand("p.multicall", 
					new Object[]{torrent.getHash(), "","p.get_address=","p.get_client_version=",
					"p.get_completed_percent=","p.get_down_rate=","p.get_down_total=",
					"p.get_id=","p.get_id_html=","p.get_options_str=","p.get_peer_rate=",
					"p.get_peer_total=","p.get_port=","p.get_up_rate=","p.get_up_total=",
					"p.is_encrypted=","p.is_incoming=","p.is_obfuscated=","p.is_snubbed="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		// Mark all existing torrents
		Iterator<Peer> it = torrent.getPeers().iterator();
		while (it.hasNext())
			it.next().setExisting(false);
		
		if (result instanceof Object[])
		{
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					Peer peer = new Peer(f[0].toString(), f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],f[5].toString(),f[6].toString(),f[7].toString(),(Long)f[8],
							(Long)f[9],(Long)f[10],(Long)f[11],(Long)f[12],(Long)f[13],
							(Long)f[14],(Long)f[15],(Long)f[16], torrent, true);
					
					// Update existing torrent
					Peer pExist = torrent.getPeers().getById(peer.getId());
					if (pExist != null)
					{
						int updated = pExist.update(f[0].toString(), f[1].toString(), (Long)f[2], (Long)f[3],
								(Long)f[4],f[5].toString(),f[6].toString(),f[7].toString(),(Long)f[8],
								(Long)f[9],(Long)f[10],(Long)f[11],(Long)f[12],(Long)f[13],
								(Long)f[14],(Long)f[15],(Long)f[16], true);
						if (updated == 1)
							torrent.getPeers().updatedPeers.add(pExist);
						peer = null;
					}
					else// Or add new one
					{
						peer.addPropertyChangeListener(torrent.getPeers());
						torrent.getPeers().add(peer);
						torrent.getPeers().newPeers.add(peer);
					}
				}
			}
		}
		
		// Remove not existing peers
		it = torrent.getPeers().iterator();
		while (it.hasNext())
		{
			Peer p = it.next();
			if (!p.isExisting())
			{
				torrent.getPeers().removedPeers.add(p);
				it.remove();
			}
		}
	}
	
	public void getTrackers(Torrent torrent) throws AnotherTorrentException
	{
		torrent.getTrackers().clear();
		
		Object result;
		try {
			result = connectionManager.sendCommand("t.multicall", 
					new Object[]{torrent.getHash(), "","t.get_group=","t.get_id=","t.get_min_interval=",
					"t.get_normal_interval=","t.get_scrape_complete=","t.get_scrape_downloaded=",
					"t.get_scrape_time_last=","t.get_type=","t.get_url=","t.is_enabled=",
					"t.is_open="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		
		if (result instanceof Object[])
		{
			Long index = 0L;
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					Tracker tracker = new Tracker(f[0].toString(), f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],(Long)f[5],(Long)f[6],(Long)f[7],f[8].toString(),
							(Long)f[9],(Long)f[10], torrent, index++);
					
					tracker.addPropertyChangeListener(torrent.getTrackers());
					torrent.getTrackers().add(tracker);
				}
			}
		}
	}
	
	public void updateTrackers(Torrent torrent) throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendCommand("t.multicall", 
					new Object[]{torrent.getHash(), "","t.get_group=","t.get_id=","t.get_min_interval=",
					"t.get_normal_interval=","t.get_scrape_complete=","t.get_scrape_downloaded=",
					"t.get_scrape_time_last=","t.get_type=","t.get_url=","t.is_enabled=",
					"t.is_open="});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
		
		if (result instanceof Object[])
		{
			Long index = 0L;
			for (Object r : ((Object[])result))
			{
				if (r instanceof Object[])
				{
					Object[] f = (Object[])r;
					
					int updated = torrent.getTrackers().get(index.intValue()).update(f[0].toString(), f[1].toString(), (Long)f[2], (Long)f[3],
							(Long)f[4],(Long)f[5],(Long)f[6],(Long)f[7],f[8].toString(),
							(Long)f[9],(Long)f[10]);
					if (updated == 1) // Add tracker to updatedTrackers
						torrent.getTrackers().updatedTrackers.add(torrent.getTrackers().get(index.intValue()));
					index++;
				}
			}
		}
	}
	
	/**
	 * The actual upload rate
	 * @return
	 */
	public Long getGlobalUpRate() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("get_up_rate");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof Long)
			return (Long)result;
		return 0L;
	}
	
	/**
	 * The actual download rate
	 * @return
	 */
	public Long getGlobalDownRate() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("get_down_rate");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof Long)
			return (Long)result;
		return 0L;
	}
	
	/**
	 * Get the upload rate limit
	 * @return
	 */
	public Long getGlobalUploadRate() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("get_upload_rate");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof Long)
			return (Long)result;
		return 0L;
	}
	
	/**
	 * Get the download rate limit
	 * @return
	 */
	public Long getGlobalDownloadRate() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("get_download_rate");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof Long)
			return (Long)result;
		return 0L;
	}
	
	/**
	 * set the upload rate limit
	 * @return
	 */
	public void setGlobalUploadRate(Long rate) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("set_upload_rate", new Object[]{rate});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	/**
	 * Set the download rate limit
	 * @return
	 */
	public void setGlobalDownloadRate(Long rate) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("set_download_rate", new Object[]{rate});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public String getGlobalClientVersion() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("system.client_version");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof String)
			return (String)result;
		return "";
	}
	
	public String getGlobalLibVersion() throws AnotherTorrentException
	{
		Object result;
		try {
			result = connectionManager.sendSimpleCommand("system.library_version");
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		if (result instanceof String)
			return (String)result;
		return "";
	}
	
	public void torrentStop(String hash) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.stop", new Object[]{hash});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentStart(String hash) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.start", new Object[]{hash});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentErase(String hash) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.erase", new Object[]{hash});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentSetPriority(String hash, Long prio) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.set_priority", new Object[]{hash, prio});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentSetFilePriority(String hash, Long fileIndex, Long prio) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("f.set_priority", new Object[]{hash, fileIndex, prio});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentAddByUrlAndStart(String url) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("load_start", new Object[]{url});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentAddByUrlAndStartWithParams(String url, TorrentCommand tc) throws AnotherTorrentException
	{
		try {
			String[] cmds = tc.getCommandArray();
			Object[] param = new Object[1 + cmds.length];
			param[0] = url;
			for (int i=0; i<cmds.length; i++) {
				param[i+1] = cmds[i];
			}
			connectionManager.sendCommand("load_start", param);
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentAddByUrlDontStart(String url) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("load", new Object[]{url});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentAddByUrlDontStartWithParams(String url, TorrentCommand tc) throws AnotherTorrentException
	{
		try {
			String[] cmds = tc.getCommandArray();
			Object[] param = new Object[1 + cmds.length];
			param[0] = url;
			for (int i=0; i<cmds.length; i++) {
				param[i+1] = cmds[i];
			}
			connectionManager.sendCommand("load", param);
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentAddByFileDontStart(java.io.File torrent) throws AnotherTorrentException
	{
		if(torrent.exists() && torrent.isFile())
		{
			try 
			{
				byte[] source = new byte[(int)torrent.length()];
				FileInputStream reader = new FileInputStream(torrent);
				reader.read(source, 0, source.length);
				connectionManager.sendCommand("load_raw", new Object[]{source});
			} catch (Exception e) {
				connectionManager.disconnect();
				throw ExceptionHandler.convert(e);
			}
		}
	}
	
	public void torrentAddByFileDontStartWithParams(java.io.File torrent, TorrentCommand tc) throws AnotherTorrentException
	{
		if(torrent.exists() && torrent.isFile())
		{
			try 
			{
				byte[] source = new byte[(int)torrent.length()];
				FileInputStream reader = new FileInputStream(torrent);
				reader.read(source, 0, source.length);
				String[] cmds = tc.getCommandArray();
				Object[] param = new Object[1 + cmds.length];
				param[0] = source;
				for (int i=0; i<cmds.length; i++) {
					param[i+1] = cmds[i];
				}
				connectionManager.sendCommand("load_raw", param);
			} catch (Exception e) {
				connectionManager.disconnect();
				throw ExceptionHandler.convert(e);
			}
		}
	}
	
	public void torrentAddByFileAndStart(java.io.File torrent) throws AnotherTorrentException
	{
		if(torrent.exists() && torrent.isFile())
		{
			try 
			{
				byte[] source = new byte[(int)torrent.length()];
				FileInputStream reader = new FileInputStream(torrent);
				reader.read(source, 0, source.length);
				connectionManager.sendCommand("load_raw_start", new Object[]{source});
			} catch (Exception e) {
				connectionManager.disconnect();
				throw ExceptionHandler.convert(e);
			} 
		}
	}
	
	public void torrentAddByFileAndStartWithParams(java.io.File torrent, TorrentCommand tc) throws AnotherTorrentException
	{
		if(torrent.exists() && torrent.isFile())
		{
			try 
			{
				byte[] source = new byte[(int)torrent.length()];
				FileInputStream reader = new FileInputStream(torrent);
				reader.read(source, 0, source.length);
				String[] cmds = tc.getCommandArray();
				Object[] param = new Object[1 + cmds.length];
				param[0] = source;
				for (int i=0; i<cmds.length; i++) {
					param[i+1] = cmds[i];
				}
				connectionManager.sendCommand("load_raw_start", param);
			} catch (Exception e) {
				connectionManager.disconnect();
				throw ExceptionHandler.convert(e);
			} 
		}
	}
	
	public void torrentSetDirectory(String hash, String dir) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.set_directory", new Object[]{hash, dir});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentCheckHash(String hash) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.check_hash", new Object[]{hash});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentSetConnectionSeed(String hash, String val) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.set_connection_seed", new Object[]{hash, val});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void torrentUpdatePriorities(String hash) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("d.update_priorities", new Object[]{hash});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void fileSetPriority(String hash, Long index, Long prio) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("f.set_priority", new Object[]{hash, index, prio});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}
	
	public void trackerSetEnabled(String hash, Long index, Long enabled) throws AnotherTorrentException
	{
		try {
			connectionManager.sendCommand("t.set_enabled", new Object[]{hash, index, enabled});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
	}

	public void torrentApplyCommands(String hash, TorrentCommand cmd) throws AnotherTorrentException {
		try {
			String[] cmds = cmd.getCommandArray();
			Object[] commands = new Object[cmds.length];
			
			for (int i=0; i<cmds.length; i++) {
				String[] c = cmds[i].split("=");
				String commandName = c[0];
				String commandValue = c.length > 1 ? c[1] : "";
				Hashtable<String, Object> oneCommand = new Hashtable<String, Object>();
				oneCommand.put("methodName", commandName);
				oneCommand.put("params", new Object[]{hash, commandValue});
				commands[i] = oneCommand;
			}
			
			connectionManager.sendCommand("system.multicall",new Object[]{commands});
		} catch (XmlRpcException e) {
			connectionManager.disconnect();
			throw ExceptionHandler.convert(e);
		}
		
	}
}
